﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;

namespace SocketClient
{
    public class SClient
    {
        private Socket socket;
        private string ip;
        private int port;

        //private ManualResetEvent sendDone = new ManualResetEvent(false);
        //private ManualResetEvent receiveDone = new ManualResetEvent(false);

        public SClient(string ip, int port)
        {
            this.ip = ip;
            this.port = port;
            connect();

            receive();
            //receiveDone.WaitOne();
        }

        private void connect()
        {
            IPAddress ipAddress = IPAddress.Parse(ip);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect(ipAddress, port);
        }

        public void Command(string command)
        {
            Command(command, string.Empty);
        }

        public void Command(string command, string data)
        {
            if (!socket.Connected)
                connect();

            send(string.Format("{0} {1}\r\n", command, data));
        }

        private void send(string data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            socket.Send(byteData);
            //socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), socket);
        }

        //private void SendCallback(IAsyncResult ar)
        //{
        //    try
        //    {
        //        // 完成数据发送.  
        //        int bytesSent = socket.EndSend(ar);
        //        Console.WriteLine("Sent {0} bytes to server.", bytesSent);

        //        // 指示数据已经发送完成，主线程继续.  
        //        sendDone.Set();
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.ToString());
        //    }

        //}


        private void receive()
        {
            Thread newThread = new Thread(receiveCore);
            newThread.Start();
        }

        private string receiveCache = string.Empty;

        private void receiveCore()
        {
            while (true)
            {

                try
                {
                    //创建一个字节数组接收数据
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    //接收数据
                    int length = socket.Receive(arrMsgRec);
                    //将字节数组转换成字符串,此时是将所有的元素都转成字符串了，而真正接收到的只有服务端发来的几个字符。
                    receiveCache += System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);

                    dealReciveData();

                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    //结束当前线程
                    //Thread.CurrentThread.Abort();
                }
            }
        }

        private void dealReciveData()
        {
            var result = receiveCache.IndexOf("\r\n");
            while (result != -1)
            {
                string text = receiveCache.Substring(0, result);
                receiveCache = receiveCache.Substring(result + 2, receiveCache.Length - result - 2);
                dealCommand(text);

                result = receiveCache.IndexOf("\r\n");
            }
        }

        private void dealCommand(string text)
        {
            var result = text.IndexOf(' ');
            if (result != -1) 
            {
                var key = text.Substring(0, result);
                var data = text.Substring(result + 1, text.Length - result - 1);

                if (commandList.ContainsKey(key))
                {
                    commandList[key](data);
                    return;
                }
            }

            if (UnkownCommandHandler != null)
                UnkownCommandHandler(text);
        }



        public void Close()
        {
            if (socket.Connected)
                socket.Shutdown(SocketShutdown.Both);
        }

        public event CommandHandler UnkownCommandHandler;

        private Dictionary<string, CommandHandler> commandList = new Dictionary<string, CommandHandler>();
        public void AddCommand(string key, CommandHandler handler)
        {
            if (commandList.ContainsKey(key))
                commandList[key] = handler;
            else
                commandList.Add(key, handler);
        }

        public void RemoveCommand(string key)
        {
            if (commandList.ContainsKey(key))
                commandList.Remove(key);
        }
    }

    public delegate void CommandHandler(string data);
}
